/*
 * UIEntity.fx
 *
 * Created on Oct 8, 2009, 12:27:41 PM
 */

package dawnland02.ui;

import javafx.animation.*;
import javafx.scene.*;
import javafx.scene.paint.Color;
import javafx.scene.shape.*;
import javafx.scene.transform.*;
import javafx.util.Math;

import dawnland02.data.map.model.MatrixDirection;
import dawnland02.model.action.Action;
import dawnland02.model.action.controller.ActionController;
import dawnland02.model.entity.Entity;
import dawnland02.model.entity.UIEntityActionHandler;
import dawnland02.model.action.ActionParam;
import dawnland02.model.action.ActionType;
import dawnland02.model.action.ActionStep;

/**
 * @author user
 */

public class UIEntity extends CustomNode, UIEntityActionHandler{
    package var entity: Entity on replace {
        entity.setUIEntityActionHandler(this);
        };
    package var uiHexagon: UIHexagon on replace {
        centerX = uiHexagon.getCenterXToParent();
        centerY = uiHexagon.getCenterYToParent();
        };
    package var uiService : UIService;

    package var centerX;
    package var centerY;
    package var rotateAngle = 0.0;

    var group : Group = Group {};

    init {
        var backgroundPolygon  = Polygon{
            points: [6, 0, 8, 6, 10, 8, 12, 12, 6, 10, 0, 12, 2, 8, 4, 6];
            fill: Color.YELLOW;          
        }
        var badgeArrow = Polygon{
            points: [6, 4.5, 8, 6.5, 8, 8, 6, 6, 4, 8, 4, 6.5];
            fill: Color.BLUE;
        }
        var badgeLine = Polygon{
            points: [8, 8.5, 8, 10, 4, 10, 4, 8.5];
            fill: Color.BLUE;
        }
        var figure = Group {
            content: [backgroundPolygon, badgeArrow, badgeLine]
        }

        def width = figure.boundsInLocal.maxX-figure.boundsInLocal.minX;
        def height = figure.boundsInLocal.maxY-figure.boundsInLocal.minY;
        def figureScaleFactor = Math.min(2* uiService.getYStep() / width, 2* uiService.getYStep() / height);
        figure.transforms = [Translate {
                x: bind centerX - width * figureScaleFactor / 2,
                y: bind centerY - height * figureScaleFactor / 2},
            Scale {
                x: figureScaleFactor;
                y: figureScaleFactor;},
            Rotate {
                angle: bind rotateAngle;
                pivotX: width / 2;
                pivotY: height / 2;
                }];
        insert figure into group.content;
    }

    override function create(): Node {
        return group;
    }

    override function handleAction(action : Action) : Void {
        if(action.getActionType() == ActionType.MOVE){
            var timeline = handleMoveAction(action);
            timeline.play();
        } else if(action.getActionType() == ActionType.ROTATE){
            var timeline = handleRotateAction(action);
            timeline.play();
        } else if(action.getActionType() == ActionType.BUILD_ROAD){
            var timeline = handleBuildRoadAction(action);
            timeline.play();
        }
    }

    function handleMoveAction(action : Action) : Timeline {
        var adiacentMatrixCellId : Integer = action.getValueForActionParam(ActionParam.MOVE_DESTINATION) as Integer;
        var currentUIHexagon = uiService.getUIMatrix().getUIHexagon(adiacentMatrixCellId);

        var keyFrames : KeyFrame[];
        var currentTime = 1s;

        var actionController : ActionController = action.getActionController();

        var moveKeyFrame = KeyFrame{
               time: currentTime;
               values: [
                   centerX => currentUIHexagon.getCenterXToParent(),
                   centerY => currentUIHexagon.getCenterYToParent(),
                   ]
               action: function() : Void {
                   this.uiHexagon = currentUIHexagon;
                   action.setCurrentStep(ActionStep.ACTION_INTERMEDIATE);
                   action.addValueForActionParam(ActionParam.MOVE_COORDINATE_X, currentUIHexagon.matrixCell.getX());
                   action.addValueForActionParam(ActionParam.MOVE_COORDINATE_Y, currentUIHexagon.matrixCell.getY());
                   actionController.act();
                   }
            };

        insert moveKeyFrame into keyFrames;

        var lastKeyFrame = KeyFrame {
            time: currentTime;
            action: function() : Void {
                action.setCurrentStep(ActionStep.ACTION_AFTER_END);
                actionController.act();
                }
        }
        insert lastKeyFrame into keyFrames;

        action.setCurrentStep(ActionStep.ACTION_BEFORE_START);
        action.addValueForActionParam(ActionParam.MOVE_DURATION, currentTime);
        actionController.act();

        Timeline {
            keyFrames: keyFrames;
        }
    }

    function handleRotateAction(action : Action) : Timeline {
        var matrixDirection : MatrixDirection = action.getValueForActionParam(ActionParam.ROTATE_DIRECTION) as MatrixDirection;

        var keyFrames : KeyFrame[];
        var currentTime = 1s;

        var actionController : ActionController = action.getActionController();
        var currentAngle = uiService.getAngle(entity.getDirection());
        var targetAngle = uiService.getAngle(matrixDirection);
        // little asjustment for targetAngle;
        // the difference targetAngle - currentAngle will be always between -180 and 180
        // so rotate will be made on closest distance
        if(targetAngle - currentAngle < -180.0){
            targetAngle+=360;
        } else if (targetAngle - currentAngle > 180.0){
            targetAngle-=360;
        }

        var rotateKeyFrame = KeyFrame {
                time: currentTime;
                values: [
                   rotateAngle => targetAngle,
                   ]
                action: function() : Void {
                   action.setCurrentStep(ActionStep.ACTION_INTERMEDIATE);
                   actionController.act();
                }
            };
        insert rotateKeyFrame into keyFrames;

        var lastKeyFrame = KeyFrame {
            time: currentTime;
            action: function() : Void {
                action.setCurrentStep(ActionStep.ACTION_AFTER_END);
                actionController.act();
                }
        }
        insert lastKeyFrame into keyFrames;

        action.setCurrentStep(ActionStep.ACTION_BEFORE_START);
        action.addValueForActionParam(ActionParam.ROTATE_DURATION, currentTime);
        actionController.act();

        Timeline {
            keyFrames: keyFrames;
        }
    }

    function handleBuildRoadAction(action : Action) : Timeline {        
        var keyFrames : KeyFrame[];

        var actionController : ActionController = action.getActionController();

        var targetAngleRightUp = uiService.getAngle(MatrixDirection.RIGHT_UP);
        var rotateRightUp = KeyFrame {
                time: 250ms;
                values: [
                   rotateAngle => targetAngleRightUp tween Interpolator.EASEIN
                   ]
            };
        insert rotateRightUp into keyFrames;

        var targetAngleLeft = uiService.getAngle(MatrixDirection.LEFT);
        var rotateLeft = KeyFrame {
                time: 700ms;
                values: [
                   rotateAngle => targetAngleLeft tween Interpolator.EASEIN
                   ]
                action: function() : Void {
                   action.setCurrentStep(ActionStep.ACTION_INTERMEDIATE);
                   actionController.act();
                }
            };
        insert rotateLeft into keyFrames;

        var targetAngleUp = uiService.getAngle(MatrixDirection.UP);
        var rotateUp = KeyFrame {
                time: 1000ms;
                values: [
                   rotateAngle => targetAngleUp
                   ]
            };
        insert rotateUp into keyFrames;

        var lastFrame = KeyFrame {
            time: 1001ms;
            action: function() : Void {
                action.setCurrentStep(ActionStep.ACTION_AFTER_END);
                actionController.act();
                uiHexagon.updateRoadLevel(uiHexagon.matrixCell.getRoadLevel());
                }
        };
        insert lastFrame into keyFrames;

        Timeline {
            keyFrames: keyFrames;
        }
    }

}
